package sound;

/**
 * @author Yogeswar Vijayakumar
 * class: AudioRecorder
 * Purpose: This class will record an audio file. 
 * Output File Format : PCM_SIGNED 8000.0 Hz, 16 bit, mono, 2 bytes/frame, big-endian *.au file
 * Input File Type : File, filepath
 * References :  
 * 1. Richard G. Baldwin - Java Sound Tutorial - http://www.developer.com/java/other/article.php/1565671/Java-Sound-An-Introduction.htm
 * 2. Richard G. Baldwin - Java Sound Recording Tutorial - http://www.developer.com/java/other/article.php/1579071
 * 																/Java-Sound-Getting-Started-Part-2-Capture-Using-Specified-Mixer.htm
 * 
 */

import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;

public class AudioRecorder {

	AudioFormat audioFormat;
	TargetDataLine targetDataLine;
	File audioFile;
	AudioFileFormat.Type fileType;
	boolean record = true;
	RecordThread RThread;
	
	public AudioRecorder()
	{
		this.audioFile = new File("recorded.au");
		this.audioFormat = new AudioFormat(	8000.0F, 16, 1,	true, false);
		this.fileType = AudioFileFormat.Type.AU;
	}
	
	public AudioRecorder(String filepath)
	{
		this.audioFile = new File(filepath);
		this.audioFormat = new AudioFormat(	8000.0F, 16, 1,	true, false);
		this.fileType = AudioFileFormat.Type.AU;
	}
	
	public AudioRecorder(String filepath, AudioFormat format)
	{
		this.audioFile = new File(filepath);
		this.audioFormat = format;
		this.fileType = AudioFileFormat.Type.AU;
	}
	
	public AudioRecorder(File file)
	{
		this.audioFile = file;
		this.audioFormat = new AudioFormat(	8000.0F, 16, 1,	true, true);
		this.fileType = AudioFileFormat.Type.AU;
	}
	
	public AudioRecorder(File file, AudioFormat format)
	{
		this.audioFile = file;
		this.audioFormat = format;
		this.fileType = AudioFileFormat.Type.AU;
	}
	
	public void setFiletype(AudioFileFormat.Type filetype)
	{
		this.fileType = filetype;
	}
	
	public AudioFileFormat.Type getFileType()
	{
		return this.fileType;
	}
	
	public void setFile(File record)
	{
		this.audioFile = record;
	}
	
	public void setFile(String filepath)
	{
		this.audioFile = new File(filepath);
	}
	
	public File getFile()
	{
		File temp = this.audioFile;
		return temp;
	}
	
	public String getFilePath()
	{
		return this.audioFile.getAbsolutePath();
	}
	
	public void setAudioFormat(AudioFormat format)
	{
		this.audioFormat = format;
	}
	
	public void setAudioFormat(float sampleRate, int sampleSizeInBits, int channels, boolean signed, boolean bigEndian)
	{
		this.audioFormat = new AudioFormat(	sampleRate,
                							sampleSizeInBits,
                							channels,
                							signed,
                							bigEndian);
	}
	
	public AudioFormat getAudioFormat()
	{
		return this.audioFormat;
	}
	
	public void startRecording()
	{
		if(this.audioFile.exists())
		{
			String path = this.audioFile.getPath();
			this.audioFile.delete();
			this.audioFile = new File(path);
			
		}
		this.record = true;
		DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class,
	                            						audioFormat);
	    try 
	    {
			targetDataLine = (TargetDataLine)AudioSystem.getLine(dataLineInfo);
			targetDataLine.open(audioFormat);
			targetDataLine.start();
		} catch (LineUnavailableException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	    
	    
	    this.RThread = new RecordThread();
	    this.RThread.start();
	}
	
	class RecordThread extends Thread
	{
		public void run()
		{		    
		    try 
		    {
				AudioSystem.write(new AudioInputStream(targetDataLine), fileType, audioFile);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
	}
	
	public void stopRecording()
	{
		targetDataLine.stop();
		targetDataLine.drain();
        targetDataLine.close();
        this.record = false;
        this.RThread.stop();
                
	}
	
	public boolean getStatus()
	{
		return this.record;
	}
	
	public static void main(String args[]) throws IOException
	{
		AudioRecorder audioRecorder = new AudioRecorder();
		System.out.println("Starting Recording");
		audioRecorder.startRecording();
		
		
		
		System.in.read();
		System.out.println("Stop Recording?");
		audioRecorder.stopRecording();
		
		System.out.println("SHall we terminated");
		System.in.read();
		
		System.in.read();
		//System.out.println("Starting Recording");
		//audioRecorder.startRecording();
		
		//System.in.read();
		//System.in.read();
		//System.out.println("Stop Recording?");
		//audioRecorder.stopRecording();
		
		System.out.println("Terminated");
	}
	  
}
